package com.yml666.jpa.utils;

import com.yml666.jpa.utils.annotation.Constraint;

import javax.persistence.Id;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Created by 19110 on 2016/9/21.
 */
public class QueryUtil {

    /**
     * 根据condition中的字段注解构建查询约束
     *
     * @param root
     * @param query
     * @param cb
     * @param condition
     * @param predicates 额外的限制
     * @param <T>
     * @return
     */
    public static <T> Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb, T condition, Collection<Predicate> predicates) {
        if (predicates == null) {
            predicates = new ArrayList<>();
        }
        try {
            Field[] fields = condition.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object value = field.get(condition);
                Constraint constraint = field.getAnnotation(Constraint.class);
                if (constraint != null && value != null) {//有约束，有值
                    switch (constraint.value()) {
                        case EQUAL:
                            predicates.add(cb.equal(root.get(field.getName()), value));
                            break;
                        case NOT_EQUAL:
                            predicates.add(cb.notEqual(root.get(field.getName()), value));
                            break;
                        case GREATER_THAN:
                            predicates.add(cb.greaterThan(root.get(field.getName()), (Comparable) value));
                            break;
                        case GREATER_THAN_OR_EQUAL_TO:
                            predicates.add(cb.greaterThanOrEqualTo(root.get(field.getName()), (Comparable) value));
                            break;
                        case LESS_THAN:
                            predicates.add(cb.lessThan(root.get(field.getName()), (Comparable) value));
                            break;
                        case LESS_THAN_OR_EQUAL_TO:
                            predicates.add(cb.lessThanOrEqualTo(root.get(field.getName()), (Comparable) value));
                            break;
                        default:
                            break;
                    }
                }
            }
        } catch (IllegalAccessException e) {

        }
        return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }
}
